﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team (cellcloudproject@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellFileExpressContext_h
#define CellFileExpressContext_h

#include "CellPrerequisites.h"
#include "CellFileExpress.h"
#include "CellFileAttribute.h"
#include "CellInet4Address.h"
#include "CellInet6Address.h"

namespace cell
{
/** 文件快递上下文。
@author
	Jiangwei Xu
*/
class _CellExport FileExpressContext : public GeneralAlloc
{
public:
	/** 用于伺服操作的构造函数。
	*/
	explicit
	FileExpressContext(const ExpressAuthCode& authCode);

	/** 用于上载操作的构造函数。
	*/
	FileExpressContext(const String& authCode,
		const InetAddress* address, const String& fullPath);

	/** 用于下载操作的构造函数。
	*/
	FileExpressContext(const String& authCode,
		const InetAddress* address, const String& fileName, const String& path);

	/**
	*/
	virtual ~FileExpressContext(void);

public:
	/** 操作类型。
	*/
	enum _Operate
	{
		/// 文件伺服
		OP_SERVO = 0,

		/// 文件上载
		OP_UPLOAD,

		/// 文件下载
		OP_DOWNLOAD
	};

	enum _ErrorCode
	{
		/// 成功
		EC_SUCCESS = 0,

		/// 网络故障
		EC_NETWORK_FAULT = 1,

		/// 未获得操作授权
		EC_UNAUTH = 2,

		/// 文件不存在
		EC_FILE_NOEXIST = 3,

		/// 因文件大小问题拒绝操作
		EC_REJECT_SIZE = 4,

		/// 数据包错误
		EC_PACKET_ERROR = 5,

		/// 存储器故障
		EC_STORAGE_FAULT = 6
	};

public:
	/**
	*/
	const ExpressAuthCode* getAuthCode(void) const;

	/**
	*/
	uint getOperate(void) const;

	/**
	*/
	const InetAddress* getAddress(void) const;

	/**
	*/
	const String& getFullPath(void) const;

	/**
	*/
	const String& getFileName(void) const;

	/**
	*/
	FileAttribute* getAttribute(void) const;

	/**
	*/
	int getErrorCode(void) const;

	/**
	*/
	long getBytesLoaded(void) const;

	/**
	*/
	long getBytesTotal(void) const;

private:
	/**
	*/
	void setErrorCode(int code);

	/**
	*/
	void setBytesLoaded(long bytes);

	/**
	*/
	void setBytesTotal(long bytes);

	/**
	*/
	void reset(const String& fileName, const String& path, const FileAttribute* attr);

	/**
	*/
	void resetFileSize(long size);

protected:
	ExpressAuthCode mAuthCode;
	uint mOperate;
	Inet4Address mAddress;

	String mFullPath;
	String mPath;
	String mFileName;

	long mBytesLoaded;
	long mBytesTotal;

	FileAttribute* mAttribute;

	int mErrorCode;

	friend class FileExpressTask;
	friend class FileExpress;
	friend class FileExpressServoContext;
};



/**
*/
class _CellExport FileExpressServoContext : public FileExpressContext
{
public:
	/**
	*/
	explicit
	FileExpressServoContext(const ExpressAuthCode& authCode);

	/**
	*/
	virtual ~FileExpressServoContext(void);

public:
	/**
	*/
	FileAttribute* getAttribute(const String& fileName) const;

	/**
	*/
	FileExpressContext* getContext(const String& fileName);

	/**
	*/
	void loadFile(const String& fileName);

	/**
	*/
	int readFile(char* data, const String& fileName, int64 offset, int length);

	/**
	*/
	void prepareFile(const String& fileName, long fileSize);

	/**
	*/
	void writeFile(const String& fileName, char* data, int64 offset, int length);

	/**
	*/
	void closeFile(const String& fileName);

	/** 返回剩余有效时间。
	*/
	int64 getRemainingTime(void) const;

private:
	/**
	*/
	SingleFileStorage* findOpenedStorage(const String& fileName);

private:
	typedef HashMap<String, SingleFileStorage*> Storages;
	typedef HashMap<String, FileExpressContext*> Contexts;
	typedef HashMap<String, ResultSet*> ReadResultSets;
	typedef HashMap<String, FileAttribute*> FileAttributes;

	uint64 mTimestamp;

	CELL_MUTEX(mMutex);
	FileAttributes mAttributes;
	Storages mStorages;
	Contexts mContexts;
	ReadResultSets mReadResultSets;
};

} // end namespace cell

#endif // CellFileExpressContext_h
